package com.fingard.dsp.bank.directbank.gzelink01;

import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.httpclient.NameValuePair;

import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.VerifyState;
import com.fingard.dsp.bank.directbank.bankInterface.IAuthentication;
import com.fingard.dsp.bank.directbank.gzelink01.util.EncryDecryUtils;
import com.fingard.dsp.bank.directbank.gzelink01.util.FormDateReportConvertor;
import com.fingard.dsp.bank.reqrespobj.auth.ReqAuth;
import com.fingard.dsp.bank.reqrespobj.auth.ReqQryAuth;
import com.fingard.dsp.bank.reqrespobj.auth.RetAtsAuth;
import com.fingard.dsp.bank.reqrespobj.auth.detail.RetAtsAuthDetail;
import com.fingard.text.StringHelper;

/**
 * 广银联鉴权
 *
 */
public class GZELINK01Authentication extends GZELINK01Base implements IAuthentication {
	public RetAtsAuth dealAuth(ReqAuth p_reqAuth) throws Exception {
		RetAtsAuth retAts = new RetAtsAuth(p_reqAuth.reqHeader);
		RetAtsAuthDetail tmpRetDetail = new RetAtsAuthDetail();
		
		try {
			String authMerId = getBankConfig().getValueAsString("authMerId");
			if (StringHelper.hasAnyChar(authMerId)) {
				ActSetItem actItem = getBankConfig().getActSetItem(authMerId, "auth");
				if (actItem != null) {
		            // 鉴权提交业务参数
		            Map<String,String> requestMap = new HashMap<String, String>();

		            // 商户订单号
		            if (StringHelper.hasAnyChar(p_reqAuth.authDetail.askNumber)) {
		            	requestMap.put("mhtOrderNo", p_reqAuth.authDetail.askNumber);
		            }
		            // 居民姓名
		            if (StringHelper.hasAnyChar(p_reqAuth.authDetail.authName)) {
		            	requestMap.put("idCardName", URLEncoder.encode(p_reqAuth.authDetail.authName, "UTF-8"));  
		            }
		            // 居民身份证(不区分英文字母大小写)
		            if (StringHelper.hasAnyChar(p_reqAuth.authDetail.certNum)) {
		            	requestMap.put("idCard", p_reqAuth.authDetail.certNum);
		            }
		            // 银行账户(卡信息验证必传)
		            if (StringHelper.hasAnyChar(p_reqAuth.authDetail.authAct)) {
		            	requestMap.put("bankCardNum", p_reqAuth.authDetail.authAct);
		            }
		            
		            String validElement = p_reqAuth.authDetail.validElement;
		            if ("4".equals(validElement)) {
		            	// 用户银行预留手机号(卡信息验证必传)
			            if (StringHelper.hasAnyChar(p_reqAuth.authDetail.cellPhone)) {
			            	requestMap.put("mobile", p_reqAuth.authDetail.cellPhone);
			            }
		            }
		            
		            //短信验证码
		            requestMap.put("msgCode", "");   
		            //保留域1 
		            requestMap.put("remarkes1", ""); 
		            //保留域2
		            requestMap.put("remarkes2", "");  
		            
		            // 请求报文原文
		            String plainMsg = FormDateReportConvertor.postFormLinkReport(requestMap).trim();
		            WriteBankLogLn2("广银联鉴权加密前业务参数明文:\r\n" + plainMsg);
		            
		            // 第一部分是base64编码的明文merchNo
		            String message1 = EncryDecryUtils.base64Encrypt("merchNo=" + actItem.merchantId);
//		            
		            // 第二部分是base64编码的3DES报文密文，且被3DES加密的内容为接口报文原文
		            String message2 = EncryDecryUtils.encryptFromDESBase64(actItem.ownKeyPassword, plainMsg);// base64(3DES(报文原文)
		            
		            // 第三部分是base64编码的MD5签名值。签名原串由“接口报文原文+&+md5Key”拼接成
		            String message3 = EncryDecryUtils.base64Encrypt(EncryDecryUtils.md5(plainMsg + "&" + actItem.saltKey));//base64(MD5(报文原文+&+ md5Key))
		            
		            String message = message1 + "|" + message2 + "|" + message3;
		            
		            NameValuePair[] param = {
		            		new NameValuePair("mode", getBankConfig().getValueAsString("modeType")), /* 接入方式: 01-测试，02-生产 */
		            		new NameValuePair("source", "01"), /* 接入来源: 接口(01) */
		            		new NameValuePair("msgFlag", "0"),  /* 短信下发标志: 0-不下发(默认) ，1-下发  */
		            		new NameValuePair("type", p_reqAuth.authDetail.authType), //接入类型：01-身份验证, 02-卡信息验证
		                    new NameValuePair("message", message)
		            };
		            
		            WriteBankLogLn2("广银联鉴权请求数据:\r\n" + getReqPostData(param));
		            
		            // 发送广银联
		            String tmpRetStr = sendAuthToBank(param, "authSubmit");
		            
		            // 解析广银联返回
		            if(tmpRetStr.split("\\|").length != 2) {
		            	// 响应成功：   1|base64(3DES(响应报文原文))|base64(MD5(响应报文原文+&+ md5Key))
			            String encryptMsg = tmpRetStr.split("\\|")[1];
			            String signMsg = tmpRetStr.split("\\|")[2];
			            
			            String originalMsg = EncryDecryUtils.decryptFromBase64DES(actItem.ownKeyPassword, encryptMsg);
			            originalMsg = URLDecoder.decode(originalMsg, "UTF-8").trim();
			            WriteBankLogLn2("广银联鉴权响应业务参数明文:\r\n" + originalMsg);
			           
			            String originalSign  =  EncryDecryUtils.base64Decrypt(signMsg).trim();
			            WriteBankLogLn2("广银联鉴权响应报文签名:\r\n" + originalSign);
			           
			            //对比签名是否验证通过
			            String localSign = EncryDecryUtils.md5(originalMsg + "&" + actItem.saltKey).trim();
			            if(originalSign.equals(localSign)){
			            	Map<String, String> respPostMap = getRespPostData(originalMsg);
			            	
			            	tmpRetDetail.respCode = "0";
		            		tmpRetDetail.respInfo = respPostMap.get("responseMsg");
		            		
		            		if (StringHelper.hasAnyChar(respPostMap.get("mhtOrderNo"))) {
		            			tmpRetDetail.reqSeqID = respPostMap.get("mhtOrderNo");
		            		} else {
		            			tmpRetDetail.reqSeqID = p_reqAuth.authDetail.askNumber;
		            		}
		            		
		            		tmpRetDetail.originalCode = respPostMap.get("responseCode");
		            		tmpRetDetail.originalInfo = respPostMap.get("responseMsg");
		            		tmpRetDetail.unifiedCode = getBankConfig().getMapValueByKey("AuthMapping", tmpRetDetail.originalCode);
		            		tmpRetDetail.unifiedInfo = respPostMap.get("responseMsg");
			            	
			            	// 鉴权成功   (0000 验证信息匹配)
			            	String tmpRespCode = respPostMap.get("responseCode");
			            	if ("0000".equals(tmpRespCode)) {
			            		tmpRetDetail.verifyState = VerifyState.SUCCESS;
			            	} else {
			            		tmpRetDetail.verifyState = VerifyState.FAIL;
			            		tmpRetDetail.failType = getBankConfig().getMapValueByKey("failTypeMapping", tmpRetDetail.originalCode);
			            	}
			            } else {
			        	    tmpRetDetail.respCode = "-1";
							tmpRetDetail.respInfo = "鉴权响应数据本地验签失败";
			            }
		            } else {
		            	// 失败返回格式:  0|base64(错误信息)
		            	tmpRetDetail.respCode = "-1";
					    tmpRetDetail.respInfo = EncryDecryUtils.base64Decrypt(tmpRetStr.split("\\|")[1]);
		            }
				} else {
					tmpRetDetail.respCode = "-1";
					tmpRetDetail.respInfo = "未找到账号:[" + authMerId + "]商户配置信息,请检查相关配置文件!";
				}
			} else {
				tmpRetDetail.respCode = "0";
				tmpRetDetail.respInfo = "广银联鉴权默认商户账号:[" + authMerId + "]内容为空,请检查相关配置文件!";
				tmpRetDetail.verifyState = VerifyState.FAIL;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			tmpRetDetail.respCode = "-1";
			tmpRetDetail.respInfo = ex.getMessage();
			WriteBankLogLn(ex);
		}
		
		if (tmpRetDetail.respCode.equals("-1") && StringHelper.isNullOrEmpty(tmpRetDetail.reqSeqID)) {
			tmpRetDetail.reqSeqID = p_reqAuth.authDetail.askNumber;
		}
		
		retAts.writeRetDetail(tmpRetDetail);
		return retAts;
	}

	public RetAtsAuth dealQryAuth(ReqQryAuth p_reqAuth) throws Exception {
		RetAtsAuth retAts = new RetAtsAuth(p_reqAuth.reqHeader);
		RetAtsAuthDetail tmpRetDetail = new RetAtsAuthDetail();
		
		try {
			String authMerId = getBankConfig().getValueAsString("authMerId");
			if (StringHelper.hasAnyChar(authMerId)) {
				ActSetItem actItem = getBankConfig().getActSetItem(authMerId, "auth");
				if (actItem != null) {
					// 鉴权查询业务参数
		            Map<String,String> requestMap = new HashMap<String, String>();
		            
		            //环境类型： 01测试 ,02生产
		            requestMap.put("mode", getBankConfig().getValueAsString("modeType")); 
		            
		            //验证类型：01身份验证, 02卡信息验证
		            requestMap.put("type", p_reqAuth.authType); 

		            // 商户订单号
		            requestMap.put("mhtOrderNo", p_reqAuth.askNumber);
		            
		            // 请求报文原文
		            String plainMsg = FormDateReportConvertor.postFormLinkReport(requestMap).trim();
		            WriteBankLogLn2("广银联鉴权查询加密前业务参数明文:\r\n" + plainMsg);
		            
		            // 第一部分是base64编码的明文merchNo
		            String message1 = EncryDecryUtils.base64Encrypt("merchNo=" + actItem.merchantId);
//		            
		            // 第二部分是base64编码的3DES报文密文，且被3DES加密的内容为接口报文原文
		            String message2 = EncryDecryUtils.encryptFromDESBase64(actItem.ownKeyPassword, plainMsg);// base64(3DES(报文原文)
		            
		            // 第三部分是base64编码的MD5签名值。签名原串由“接口报文原文+&+md5Key”拼接成
		            String message3 = EncryDecryUtils.base64Encrypt(EncryDecryUtils.md5(plainMsg + "&" + actItem.saltKey));//base64(MD5(报文原文+&+ md5Key))
		            
		            String message = message1 + "|" + message2 + "|" + message3;
		            
		            NameValuePair[] param = {
		            		new NameValuePair("mode", getBankConfig().getValueAsString("modeType")), /* 接入方式: 01-测试，02-生产 */
		            		new NameValuePair("type", p_reqAuth.authType), /* 接入类型：01-身份验证, 02-卡信息验证 */
		                    new NameValuePair("message", message)
		            };
		            
		            WriteBankLogLn2("广银联鉴权查询请求数据:\r\n" + getReqPostData(param));
		            
		            // 发送广银联
		            String tmpRetStr = sendAuthToBank(param, "authQuery");
		            
		            // 解析广银联返回
		            if(tmpRetStr.split("\\|").length != 2) {
		            	// 响应成功：   1|base64(3DES(响应报文原文))|base64(MD5(响应报文原文+&+ md5Key))
			            String encryptMsg = tmpRetStr.split("\\|")[1];
			            String signMsg = tmpRetStr.split("\\|")[2];
			            
			            String originalMsg = EncryDecryUtils.decryptFromBase64DES(actItem.ownKeyPassword, encryptMsg);
			            originalMsg = URLDecoder.decode(originalMsg, "UTF-8").trim();
			            WriteBankLogLn2("广银联鉴权查询响应业务参数明文:\r\n" + originalMsg);
			           
			            String originalSign  =  EncryDecryUtils.base64Decrypt(signMsg).trim();
			            WriteBankLogLn2("广银联鉴权查询响应报文签名:\r\n" + originalSign);
			           
			            //对比签名是否验证通过
			            String localSign = EncryDecryUtils.md5(originalMsg + "&" + actItem.saltKey).trim();
			            if(originalSign.equals(localSign)){
			            	Map<String, String> respPostMap = getRespPostData(originalMsg);
			            	
			            	tmpRetDetail.respCode = "0";
		            		tmpRetDetail.respInfo = respPostMap.get("responseMsg");
		            		
		            		if (StringHelper.hasAnyChar(respPostMap.get("mhtOrderNo"))) {
		            			tmpRetDetail.reqSeqID = respPostMap.get("mhtOrderNo");
		            		} else {
		            			tmpRetDetail.reqSeqID = p_reqAuth.askNumber;
		            		}
		            		
		            		tmpRetDetail.originalCode = respPostMap.get("responseCode");
		            		tmpRetDetail.originalInfo = respPostMap.get("responseMsg");
		            		tmpRetDetail.unifiedCode = getBankConfig().getMapValueByKey("AuthMapping", tmpRetDetail.originalCode);
		            		tmpRetDetail.unifiedInfo = respPostMap.get("responseMsg");
		            		
		            		String tmpRespCode = respPostMap.get("responseCode");
			            	if ("0000".equals(tmpRespCode)) {
			            		tmpRetDetail.verifyState = VerifyState.SUCCESS;
			            	} else {
			            		tmpRetDetail.verifyState = VerifyState.FAIL;
			            		tmpRetDetail.failType = getBankConfig().getMapValueByKey("failTypeMapping", tmpRetDetail.originalCode);
			            	}
			            } else {
			        	    tmpRetDetail.respCode = "-1";
							tmpRetDetail.respInfo = "鉴权响应数据本地验签失败";
			            }
		            } else {
		            	// 失败返回格式:  0|base64(错误信息)
		            	tmpRetDetail.respCode = "-1";
					    tmpRetDetail.respInfo = EncryDecryUtils.base64Decrypt(tmpRetStr.split("\\|")[1]);
		            }
				} else {
					tmpRetDetail.respCode = "-1";
					tmpRetDetail.respInfo = "未找到账号:[" + authMerId + "]商户配置信息";
				}
			} else {
				tmpRetDetail.respCode = "-1";
				tmpRetDetail.respInfo = "广银联鉴权默认商户账号:[" + authMerId + "]内容为空,请检查相关配置文件!";
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			tmpRetDetail.respCode = "-1";
			tmpRetDetail.respInfo = ex.getMessage();
			WriteBankLogLn(ex);
		}
		
		if (tmpRetDetail.respCode.equals("-1") && StringHelper.isNullOrEmpty(tmpRetDetail.reqSeqID)) {
			tmpRetDetail.reqSeqID = p_reqAuth.askNumber;
		}
		
		retAts.writeRetDetail(tmpRetDetail);
		return retAts;
	}
}
